package com.zyc.remoting.transport.socket;


import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.zyc.config.CustomShutdownHook;
import com.zyc.factory.SingletonFactory;
import com.zyc.provider.ServiceProvider;
import com.zyc.provider.impl.ZKServiceProviderImpl;
import com.zyc.utils.threadpool.RpcThreadPoolConfig;
import com.zyc.utils.threadpool.RpcThreadPoolFactoryUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author zyc
 * @create 2022--05--09 10:51
 */
@Slf4j
@Component
public class SocketRpcServer {
    private final ThreadPoolExecutor threadPool;
    private final ServiceProvider serviceProvider;


    public SocketRpcServer() {
        threadPool = RpcThreadPoolFactoryUtil.createThreadPoolIfAbsent("socket线程池");
        serviceProvider = SingletonFactory.getInstance(ZKServiceProviderImpl.class);
    }


    public void registerService(Object service) {
        serviceProvider.publishService(service);
    }

    public void start() {
        try (ServerSocket server = new ServerSocket(SocketConstant.servicePort)) {
            // 关机钩子方法，在关机前清除zookeeper中的节点。
            CustomShutdownHook.getCustomShutdownHook().clearAll(SocketConstant.servicePort);
            Socket socket;
            log.info("监听端口{}的请求",SocketConstant.servicePort);
            while ((socket = server.accept()) != null) {
                log.info("=============客户端{}已连接===============", socket.getInetAddress());
                threadPool.execute(new SocketRpcServerRunnable(socket));
            }
            threadPool.shutdown();
        } catch (IOException e) {
            log.error("出现异常", e);
        }
    }

    /**
     * 以指定端口发布服务
     * @param port
     */
    public void registerService(Object service, int port) {
        serviceProvider.publishService(service, port);
    }

    /**
     * 以指定端口运行
     * @param port
     */
    public void start(int port) {
        try (ServerSocket server = new ServerSocket(port)) {
            CustomShutdownHook.getCustomShutdownHook().clearAll(port);
            Socket socket;
            log.info("监听端口{}的请求",port);
            while ((socket = server.accept()) != null) {
                log.info("=============客户端{}已连接===============", socket.getInetAddress());
                threadPool.execute(new SocketRpcServerRunnable(socket));
            }
            threadPool.shutdown();
        } catch (IOException e) {
            log.error("出现异常", e);
        }
    }

}
